home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-12-20 | 18.4 KB | 591 lines | [TEXT/ALFA] |
- ## -*-Tcl-*-
- # ###################################################################
- # Vince's Additions - an extension package for Alpha
- #
- # FILE: "alphaHooks.tcl"
- # created: 18/7/97 {5:10:18 pm}
- # last update: 20/12/97 {7:18:17 pm}
- # Author: Vince Darley
- # E-mail: <darley@fas.harvard.edu>
- # mail: Division of Engineering and Applied Sciences, Harvard University
- # Oxford Street, Cambridge MA 02138, USA
- # www: <http://www.fas.harvard.edu/~darley/>
- #
- # Copyright (c) 1997 Vince Darley
- #
- # Description:
- #
- # Here are the current hooks:
- #
- # activateHook changeMode closeHook deactivateHook modifyModeFlags
- # quitHook resumeHook saveasHook saveHook savePostHook suspendHook
- # openHook
- #
- # There's also a 'mode::init' hook which will be called the first
- # time a mode is started up. Note that the mode exists, but its
- # variables have not yet been made global, and its menus have not
- # yet been inserted into the menu bar.
- #
- # There's also a 'startupHook' which is called when Alpha starts
- # up, but after all other initialisation has taken place (before
- # any files are opened though).
- #
- # There's also a 'launch' hook for when an app is launched.
- #
- # Use of such lists as 'savePostHooks' is obsolete.
- # These lists are ignored, use hook::register instead.
- #
- # History
- #
- # modified by rev reason
- # -------- --- --- -----------
- # 18/7/97 VMD 1.0 original
- # 22/7/97 VMD 1.1 fixed all bugs ;-) and added the above examples.
- # ###################################################################
- ##
-
- namespace eval mode {}
- namespace eval win {}
-
- proc saveHook name {
- global backup backupExtension backupFolder mode win::Modes \
- backupAgeRequirementInHours
- hook::callAll saveHook [set win::Modes($name)] $name
- if $backup {
- set dir $backupFolder
-
- if {![string length $dir]} {
- set dir [file dirname $name]
- }
- if {![file exists $dir]} {
- if {[dialog::yesno "Create backup dir '$dir'?"]} {
- mkdir $dir
- }
- }
- set backfile $dir:[file tail $name]$backupExtension
- if {[file exists $backfile]} {
- getFileInfo $name a
- if {[expr ([now] - $a(modified) + 0.0)/3600] < $backupAgeRequirementInHours} {
- return
- }
- catch {removeFile $backfile}
- }
- message "Backing up…$backfile"
- catch {copyFile $name $backfile}
- }
- }
-
- proc saveUnmodified {} {
- set name [win::Current]
- if {[file exists $name] || \
- ([regsub { <\w+>$} $name {} name] && [file exists $name])} {
- getFileInfo $name arr
- set mod $arr(modified)
- save
- setFileInfo $name modified $mod
- return
- }
- # shouldn't really get here!
- error "File doesn't exist"
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "changeMode" --
- #
- # A very important procedure. It handles all switching from one mode
- # to another. This means it has to adjust menus, floating windows,
- # global variables, mode prefs, and call a number of hooks.
- #
- # It maintains a list of variables which the new mode over-rides from
- # the global scope, and recreates them. This allows a mode to have
- # its own value for a global variable without messing anything up.
- # -------------------------------------------------------------------------
- ##
- proc changeMode {newMode} {
- global lastMode modeMenus dummyProc mode seenMode PREFS globalMenus_curr
- global global::_vars
-
- set lastMode $mode
- set mode $newMode
- if {$lastMode == $mode} {
- catch {displayMode $newMode}
- return
- } elseif {$lastMode == ""} {
- catch {menuEnableHook 1}
- } elseif {$mode == ""} {
- catch {menuEnableHook 0}
- }
- global ${lastMode}modeVars
- if {[info exists ${lastMode}modeVars]} {
- foreach v [array names ${lastMode}modeVars] {
- global $v
- catch {unset $v}
- }
- }
- floatShowHide off $lastMode
- if [info exists global::_vars] {
- uplevel \#0 ${global::_vars}
- unset global::_vars
- }
- if {[info exists modeMenus($lastMode)]} {
- if {[info exists modeMenus($mode)]} {
- set oldMenus modeMenus($mode)
- } else {
- set oldMenus ""
- }
- foreach m $modeMenus($lastMode) {
- if {([lsearch $globalMenus_curr $m] < 0) && ([lsearch $oldMenus $m] < 0)} {
- global $m
- catch {removeMenu [set $m]}
- }
- }
- }
-
- # These lines must load the mode vars into the mode var scope.
- if {[info exists dummyProc($mode)]} { $dummyProc($mode) }
- if {![info exists seenMode($mode)]} {
- hook::callAll mode::init $mode
- }
- # once the vars are in mode-var scope (= the <mode>modeVars array),
- # they can be transfered to the global scope. A future version of
- # Alpha with Tcl8.0 namespaces may not need to do this.
- global ${mode}modeVars
- if {[info exists ${mode}modeVars]} {
- foreach v [array names ${mode}modeVars] {
- global $v
- if [info exists $v] { append global::_vars "set $v \{[set $v]\} ;" }
- set $v [set ${mode}modeVars($v)]
- }
- }
- if {[info exists modeMenus($mode)]} {
- foreach m $modeMenus($mode) {
- catch {$m}
- global $m
- catch {insertMenu [set $m]}
- }
- }
-
- floatShowHide on $mode
-
- if {![info exists seenMode($mode)]} {
- set seenMode($mode) 1
- if {($mode != "") && [file exists "$PREFS:${mode}Prefs.tcl"]} {
- if {[catch {uplevel \#0 [list source "$PREFS:${mode}Prefs.tcl"]}]} {
- alertnote "Your preferences file '${mode}Prefs.tcl has an error."
- }
- }
- }
-
- catch {displayMode $newMode}
-
- hook::callAll changeMode $mode $mode
- }
- ##
- # -------------------------------------------------------------------------
- #
- # "requireOpenWindowsHook" --
- #
- # En-/disable meaningless menu items which would require the presence
- # of a certain number of windows to be active
- #
- # This proc should only be called from 'openHook' and 'closeHook'.
- #
- # You can register with it using
- #
- # 'hook::register requireOpenWindowsHook [list menu item] N'
- #
- # where 'N' is the number of windows required (1 or 2 usually)
- # (and deregister etc using hook::deregister).
- #
- # We only really need the catch in here for two reasons:
- # (i) in case bad menus are registered accidentally
- # (ii) so startup errors can open a window without hitting another error
- # in the middle of doing that!
- # -------------------------------------------------------------------------
- ##
- proc requireOpenWindowsHook {requiredNum} {
- foreach count $requiredNum {
- set enable [expr [llength [winNames]] >= $requiredNum ? 1 : 0]
- foreach i [hook::list requireOpenWindowsHook $requiredNum] {
- catch "enableMenuItem $i $enable"
- }
- }
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "menuEnableHook" --
- #
- # This hook is called to turn menu items on or off. It is called
- # whenever there are no windows, or when we go from 0->1 window.
- #
- # It should deal with all standard menus. It does not deal with
- # special menu items like 'save', 'revert',.. which require more
- # information.
- #
- # It is called from changeMode.
- #
- # Andreas wrote most of this proc.
- #
- # Due to a deficiency in MacOS/MercutioMDEF/Alpha (not sure who
- # the culprit is!), key-bindings attached to menu items are still
- # triggered even if the menu item is inactive.
- # -------------------------------------------------------------------------
- ##
- proc menuEnableHook {{haveWin 1}} {
- global winMenu
- # we only get here if there are no windows, or 1 window which we
- # just opened. Otherwise nothing will be different to last time.
- enableMenuItem Config currentMode $haveWin
- enableMenuItem File close $haveWin
- enableMenuItem File closeAll $haveWin
- enableMenuItem File closeFloat $haveWin
- enableMenuItem File saveAs… $haveWin
- enableMenuItem File saveACopyAs… $haveWin
- if {[package::active printerChoicesMenu]} {
- enableMenuItem File print $haveWin
- } else {
- enableMenuItem File print… $haveWin
- }
- eval [lindex [list un {}] $haveWin]bind 'p' <c> print
-
- enableMenuItem Edit undo $haveWin
- enableMenuItem Edit redo $haveWin
- enableMenuItem Edit load $haveWin
- enableMenuItem Edit cut&Append $haveWin
- enableMenuItem Edit copy&Append $haveWin
- enableMenuItem Edit pastePop $haveWin
- enableMenuItem Edit selectParagraph $haveWin
- enableMenuItem Edit twiddle $haveWin
- enableMenuItem Edit twiddleWords $haveWin
- enableMenuItem Edit shiftLeft $haveWin
- enableMenuItem Edit shiftLeftSpace $haveWin
- enableMenuItem Edit shiftRight $haveWin
- enableMenuItem Edit shiftRightSpace $haveWin
- enableMenuItem Edit balance $haveWin
- enableMenuItem Edit emacs $haveWin
-
- enableMenuItem Text fillParagraph $haveWin
- enableMenuItem Text wrapParagraph $haveWin
- enableMenuItem Text sentenceParagraph $haveWin
- enableMenuItem Text fillRegion $haveWin
- enableMenuItem Text wrapRegion $haveWin
- enableMenuItem Text sentenceRegion $haveWin
- enableMenuItem Text paragraphToLine $haveWin
- enableMenuItem Text lineToParagraph $haveWin
- enableMenuItem Text reverseSort $haveWin
- enableMenuItem Text sortLines $haveWin
- enableMenuItem Text spellcheckWindow $haveWin
- enableMenuItem Text spellcheckSelection $haveWin
- enableMenuItem Text zapInvisibles $haveWin
- enableMenuItem Text tabsToSpaces $haveWin
- enableMenuItem Text spacesToTabs $haveWin
- enableMenuItem Text indentLine $haveWin
- enableMenuItem Text indentRegion $haveWin
- enableMenuItem Text upcaseRegion $haveWin
- enableMenuItem Text downcaseRegion $haveWin
- enableMenuItem Text strings $haveWin
- enableMenuItem Text commentLine $haveWin
- enableMenuItem Text uncommentLine $haveWin
- enableMenuItem Text commentBox $haveWin
- enableMenuItem Text uncommentBox $haveWin
- enableMenuItem Text commentParagraph $haveWin
- enableMenuItem Text uncommentParagraph $haveWin
- enableMenuItem Text gotoFunc $haveWin
- # These four don't work because of a bug in Alpha.
- # It won't recognise items near the end of long menus
- # (long is > 20 items or so). We leave them in hoping
- # for the future...
- enableMenuItem Text gotoFileMark $haveWin
- enableMenuItem Text markHilite $haveWin
- enableMenuItem Text namedMarks $haveWin
- enableMenuItem Text unnamedMarks $haveWin
- # Temporary work-around: disable all submenu items
- enableMenuItem namedMarks set… $haveWin
- enableMenuItem namedMarks goto… $haveWin
- enableMenuItem namedMarks remove… $haveWin
- enableMenuItem namedMarks sort $haveWin
- enableMenuItem namedMarks sortByPosition $haveWin
- enableMenuItem unnamedMarks set… $haveWin
- enableMenuItem unnamedMarks exchangePointAndMark $haveWin
-
- enableMenuItem Search searchStart $haveWin
- enableMenuItem Search findAgain $haveWin
- enableMenuItem Search findAgainBackward $haveWin
- enableMenuItem Search enterSearchString $haveWin
- enableMenuItem Search enterReplaceString $haveWin
- enableMenuItem Search quickFind $haveWin
- enableMenuItem Search quickFindRegexp $haveWin
- enableMenuItem Search reverseQuickFind $haveWin
- enableMenuItem Search replace $haveWin
- enableMenuItem Search replace&FindAgain $haveWin
- enableMenuItem Search replaceAll $haveWin
- enableMenuItem Search pushPosition $haveWin
- enableMenuItem Search popPosition $haveWin
- enableMenuItem Search gotoLine $haveWin
-
- enableMenuItem Utils AsciiEtc $haveWin
- enableMenuItem Utils matchingLines $haveWin
- enableMenuItem Utils gotoMatch $haveWin
- enableMenuItem Utils nextMatch $haveWin
- enableMenuItem Utils cmdDoubleClick $haveWin
- enableMenuItem Utils winUtils $haveWin
-
- enableMenuItem Config setFontsTabs… $haveWin
- enableMenuItem Config currentMode $haveWin
-
- enableMenuItem $winMenu zoom $haveWin
- enableMenuItem $winMenu singlePage $haveWin
- enableMenuItem $winMenu chooseAWindow $haveWin
- enableMenuItem $winMenu iconify $haveWin
- enableMenuItem $winMenu arrange $haveWin
- enableMenuItem $winMenu splitWindow $haveWin
- enableMenuItem $winMenu toggleScrollbar $haveWin
-
- if {!$haveWin} {
- enableMenuItem File save 0
- enableMenuItem File saveUnmodified 0
- enableMenuItem File revert 0
- enableMenuItem File revertToBackup 0
- enableMenuItem File renameTo… 0
- enableMenuItem File saveAll 0
- }
-
- requireOpenWindowsHook 1
- }
-
- proc savePostHook name {
- hook::callAll savePostHook "" $name
- }
-
- proc closeHook name {
- global markStack win::Modes win::Active win::Current win::Dirty win::NumDirty
- hook::callAll closeHook [set win::Modes($name)] $name
-
- if {[info exists win::Dirty($name)]} {
- incr win::NumDirty -1
- unset win::Dirty($name)
- enableMenuItem File saveAll [expr ${win::NumDirty} ? 1 : 0]
- }
-
- unset win::Modes($name)
- if [llength $markStack] {
- set markStack [lremove -glob $markStack $name*]
- }
- win::removeFromMenu $name
-
- if {[set ind [lsearch ${win::Active} $name]] >= 0} {
- set win::Active [lreplace ${win::Active} $ind $ind]
- }
- if {![llength [winNames]]} {
- set win::Current ""
- changeMode {}
- }
- requireOpenWindowsHook 2
- }
-
- proc deactivateHook name {
- hook::callAll deactivateHook "" $name
- }
-
- proc suspendHook name {
- hook::callAll suspendHook "" $name
- global iconifyOnSwitch
- global suspIconed
- if {$iconifyOnSwitch} {
- set wins [winNames -f]
- set suspIconed ""
- foreach win $wins {
- if {![icon -f "$win" -q]} {
- lappend suspIconed $win
- icon -f "$win" -t
- }
- }
- set suspIconed [lreverse $suspIconed]
- }
- }
-
- ensureset killCompilerErrors 0
- proc resumeHook name {
- global iconifyOnSwitch resumeRevert suspIconed killCompilerErrors
-
- if {$killCompilerErrors} {
- set wins [winNames -f]
- if {[set res [lsearch $wins "*Compiler Errors*"]] >= 0} {
- bringToFront [lindex $wins $res]
- killWindow
- }
- }
-
- if {$iconifyOnSwitch && [info exists suspIconed]} {
- set wins [winNames -f]
- foreach win $suspIconed {
- icon -f "$win" -o
- }
- unset suspIconed
- }
- if {$resumeRevert} {
- set resumeRevert 0
- revert
- }
- hook::callAll resumeHook "" $name
- }
-
- # Added 'refresh'
- # Added oldName as an argument to hook::callAll
- # All saveasHooks should take these two arguments.
- # I needed both args in a hook I just made...
- proc saveasHook {oldName newName} {
- global win::Modes win::Active
- if {$oldName == $newName} return
- win::removeFromMenu $oldName
- win::addToMenu $newName
- win::setMode $newName
- changeMode [set win::Modes($newName)]
-
- hook::callAll saveasHook [set win::Modes($newName)] $oldName $newName
-
- if {[set ind [lsearch ${win::Active} $oldName]] >= 0} {
- set win::Active [lreplace ${win::Active} $ind $ind]
- }
- set win::Active [linsert ${win::Active} 0 $newName]
- catch {unset win::Modes($oldName)}
- refresh
- }
- ensureset win::Active ""
-
- proc activateHook {name} {
- global win::Modes win::Active win::Current
-
- if {![info exists win::Modes($name)]} {
- win::setMode $name
- }
- if {[set ind [lsearch -exact ${win::Active} $name]] == -1} {
- set win::Active [linsert ${win::Active} 0 $name]
- } elseif {$ind >= 1} {
- set win::Active [lreplace ${win::Active} $ind $ind]
- set win::Active [linsert ${win::Active} 0 $name]
- }
- set win::Current $name
-
- changeMode [set win::Modes($name)]
-
- hook::callAll activateHook [set win::Modes($name)] $name
-
- # if the file exists (this seems to be the quickest way to check)
- if {[file exists $name] || \
- ([regsub { <\w+>$} $name {} nm] && [file exists $nm])} {
- # this fails if the window is just opening, but then we know it's clean
- if [catch {getWinInfo -w $name arr}] {
- set dirty 0
- } else {
- set dirty $arr(dirty)
- }
- enableMenuItem File save $dirty
- enableMenuItem File saveUnmodified $dirty
- enableMenuItem File revert $dirty
- enableMenuItem File revertToBackup 1
- enableMenuItem File renameTo… 1
- } else {
- enableMenuItem File save 0
- enableMenuItem File saveUnmodified 0
- enableMenuItem File revert 0
- enableMenuItem File revertToBackup 0
- enableMenuItem File renameTo… 0
- }
-
- }
-
- proc quitHook {} {
- global PREFS
- if {[file exists "$PREFS:ftpTmp"]} {
- catch {rm "$PREFS:ftpTmp:*"}
- }
- saveModifiedVars
- hook::callAll quitHook
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "dirtyHook" --
- #
- # This proc currently has to keep track in the array 'win::Dirty' of
- # the dirty status of windows. Its only use is if we close a dirty
- # window and select 'discard', we would otherwise have a faulty
- # 'win::NumDirty' count. If there's a different solution we should
- # get rid of the win::Dirty array.
- #
- # Note: closeHook is called after the window is gone, and killWindow
- # isn't called if you click in the close-box, so they don't solve
- # the problem.
- # -------------------------------------------------------------------------
- ##
- proc dirtyHook {name dirty} {
- global winMenu win::NumDirty win::Dirty
- markMenuItem $winMenu [file tail $name] $dirty "◊"
- if {$dirty == "on"} {
- set win::Dirty($name) 1
- incr win::NumDirty 1
- } else {
- catch {unset win::Dirty($name)}
- incr win::NumDirty -1
- }
- enableMenuItem File save $dirty
- enableMenuItem File saveUnmodified $dirty
- enableMenuItem File revert $dirty
- enableMenuItem File saveAll [expr ${win::NumDirty} ? 1 : 0]
- # we may still revertToBackup even if the file is clean.
- # however we can't just revert.
- }
-
- proc openHook name {
- global win::Modes autoMark mode screenHeight screenWidth \
- forceMainScreen
-
- changeMode [set win::Modes($name)]
- regsub -all {\\([][])} $name {\1} nm
- win::addToMenu $nm
- message ""
-
- if {![catch {getFileInfo $name info}]} {
- if {$info(creator) == {ttxt}} {
- setWinInfo dirty 0
- }
- if {$info(type) == {ttro}} {
- catch {setWinInfo read-only 1}
- message "Read-only!"
- }
- }
-
- global ${mode}modeVars
-
- if {$forceMainScreen} {
- set geo [getGeometry]
- set l [lindex $geo 0]; set t [lindex $geo 1]; set w [lindex $geo 2]; set h [lindex $geo 3];
- if {($l < 0) || ($t < 35) || ([expr $l + $w] > $screenWidth) || ([expr $t + $h + 18] > $screenHeight)} {
- singlePage
- }
- }
- getWinInfo arr
- if !$arr(read-only) {
- if {[info exists ${mode}modeVars(autoMark)] \
- && [set ${mode}modeVars(autoMark)] \
- && ![llength [getNamedMarks -n]]} {
- markFile
- }
- }
-
- global PREFS
- if {[string match "${PREFS}*defs.tcl" $name]} {setWinInfo read-only 1}
-
- requireOpenWindowsHook 2
-
- hook::callAll openHook [set win::Modes($name)] $name
- }
-
-
-